home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
lib
/
amiga
/
cstack.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
3KB
|
130 lines
/*
* CSTACK.C
*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*
* Dynamic Stack Allocation. If this library module is brought it
* then dynamic stacking is in effect.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <exec/types.h>
#include <exec/tasks.h>
#include <clib/exec_protos.h>
extern long _cur_fudge;
extern long _cur_chunk;
extern char *_stk_base;
extern long _stack_fudge;
extern long _stack_chunk;
extern __stkargs void _stk_free(void);
extern __stkargs void _stack_panic(const char *);
/*
* _CStackAlloc(&ctlframe)
*/
__stkargs
void *
_CStackAlloc(psf, a5space)
long *psf;
long a5space;
{
char *new;
char *tmp;
long bytes = _stack_chunk; // minimum stack chunking size
long copybytes = psf[1] + // arguments passed by original caller
4 + // return vector by original caller
psf[0] + // registers saved by callee
4; // fp pushed by callee
if (bytes < copybytes + a5space + 256)
bytes = copybytes + a5space + 256;
//printf("bytes=%d copybytes=%d a5space=%d\n", bytes, copybytes, a5space);
/*
* allocate new stack
*/
while ((new = malloc(bytes + _stack_fudge)) == NULL)
stack_abort();
//printf("newstack %08lx-%08lx\n", new, bytes + _stack_fudge);
/*
* alloc space off the top of the new space to copy the original
* procedural arguments, return vector, callee's saved registers,
* and A5.
*/
tmp = new + bytes + _stack_fudge;
tmp -= copybytes; // caller args, rts vec, callee regs, callee fp
movmem((char *)psf + 8, tmp, copybytes);
/*
* setup the return vector on the new stack to point to stk_free,
* setup the return FP to point to the real return FP on the original
* stack. The real return FP on the original stack is moved to the
* top of the saved registers on the original stack.
*/
extern void main();
//printf("returnvector %08lx main %08lx (%08lx)\n",
// *(long *)(tmp + 4 + psf[0]),
// main,
// *(long *)(tmp + 4 + psf[0]) - (long)main,
//);
*(long *)(tmp + 4 + psf[0]) = (long)_stk_free;
*(long *)(tmp) = (long)((char *)psf + 8 + psf[0]);
*(long *)((char *)psf + 8 + psf[0]) = psf[2];
/*
* save old stack information
*/
((long *)new)[0] = 0; // currently unused field.
((long *)new)[1] = (long)_stk_base;
((long *)new)[2] = _cur_fudge;
((long *)new)[3] = bytes;
_cur_fudge = _stack_fudge;
_cur_chunk = _stack_chunk;
_stk_base = new + _cur_fudge;
//printf("return %08lx\n", tmp);
return(tmp);
}
/*
* CStackFree is called to free up the current stack frame. We have
* already been moved back to the old stack.
*/
__stkargs
void
_CStackFree()
{
char *old = _stk_base - _cur_fudge;
void x;
if ((char *)&x >= old && (char *)&x < old + _cur_fudge + _cur_chunk)
_stack_panic("badstkptr");
if (_cur_chunk == 0)
_stack_panic("chksz0");
//printf("restore frame %08lx\n", ((long *)old)[1]);
_stk_base = (char *)((long *)old)[1];
_cur_fudge = ((long *)old)[2];
_cur_chunk = ((long *)old)[3];
free(old);
}